package com.snail.auth.service;

import com.common.util.StringUtil;
import com.snail.auth.dao.AuthMenuRep;
import com.snail.auth.entity.AuthMenu;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

@Service
@Transactional
public class AuthMenuService {
    @Autowired
    private AuthMenuRep menuRep;


    public AuthMenu save(AuthMenu entity) {
        if (entity.getFlag() == null) {
            entity.setFlag(0);
        }
        return menuRep.saveAndFlush(entity);
    }

    public void del(Long id) {
        menuRep.deleteById(id);
    }

    List<AuthMenu> findByParentId(Long parentId) {
        return menuRep.execHql("from AuthMenu where parentId='" + parentId + "' and flag=0 ");
    }

    /**
     * 获取所有菜单
     */
    public List<AuthMenu> list() {
        return menuRep.execHql("from AuthMenu where flag=0 order by sort");
    }

    public AuthMenu getByKey(Long id) {
        Optional obj = menuRep.findById(id);
        if (obj.isPresent()) {
            return (AuthMenu) obj.get();
        }
        return null;
    }

    public Long newId(Long parentId) {
        if (parentId == null || parentId == 0L) {
            List<AuthMenu> list = menuRep.execHql("from AuthMenu where parentId=0 order by id desc");
            if (list.size() > 0) {
                return list.get(0).getId() + 1;
            }
            return 10L;
        } else {
            List<AuthMenu> list = menuRep.execHql("from AuthMenu where parentId=" + parentId + " order by id desc");
            if (list.size() > 0) {
                return list.get(0).getId() + 1;
            } else {
                return parentId * 100 + 1;
            }
        }
    }

    /**
     * 根据userId获取用户具有权限的菜单信息
     */
    public List<Map<String, Object>> getUserMenu(Long userId) {
        List<AuthMenu> menus = new ArrayList<>();
        if (userId != 0) {
            menus = getByUser(userId);
        } else {
            menus = list();//超级管理员
        }
        //根据底层菜单穷尽上级菜单
        if (menus != null && menus.size() > 0) {
            return menuTree(menus);
        }
        return null;
    }

    /**
     * 根据userid获取用户具有权限的菜单list
     */
    private List<AuthMenu> getByUser(Long userId) {
        String sql = "select am.* from auth_menu am " +
                " where am.id in " +
                "   (select aa.menu_id from auth_authority aa where aa.id in " +
                "       (select ra.authority_id from auth_role_authority ra where ra.role_id = (" +
                "           select ur.role_id from auth_user_role ur where ur.user_id=" + userId + "))) ";
        System.out.println("查询用户有权的底层菜单 sql = " + sql);
        List<Map<String, Object>> menuMaps = menuRep.execSql(sql);
        if (menuMaps.size() > 0) {
            //以下根据底层菜单获取父级菜单，构成显示用完整的菜单list
            Set<AuthMenu> menuSet = new HashSet<>();
            List<AuthMenu> allmenus = list();//所有系统菜单
            Map<Long, AuthMenu> allMap = new HashMap<>();
            for (AuthMenu menu : allmenus) {
                allMap.put(menu.getId(), menu);
            }
            for (Map<String, Object> menu : menuMaps) {
                if (allMap.containsKey(Long.valueOf(menu.get("id").toString()))) {//一级    一层菜单
                    AuthMenu rawMenu = allMap.get(Long.valueOf(menu.get("id").toString()));
                    menuSet.add(rawMenu);
                    if (allMap.containsKey(rawMenu.getParentId())) {//是否有下一级      二层菜单
                        AuthMenu firstMenu = allMap.get(rawMenu.getParentId());
                        menuSet.add(firstMenu);
                        if (allMap.containsKey(firstMenu.getParentId())) {//是否有下一级     三层菜单
                            AuthMenu secMenu = allMap.get(firstMenu.getParentId());
                            menuSet.add(secMenu);
                            if (allMap.containsKey(secMenu.getParentId())) {//是否有下一级       四层菜单
                                AuthMenu thirdMenu = allMap.get(secMenu.getParentId());
                                menuSet.add(thirdMenu);
                                if (allMap.containsKey(thirdMenu.getParentId())) {//是否有下一级       五层菜单
                                    AuthMenu fourMenu = allMap.get(thirdMenu.getParentId());
                                    menuSet.add(fourMenu);
                                }
                            }
                        }
                    }
                }
            }
            List<AuthMenu> menuList = new ArrayList<>(menuSet);
            Collections.sort(menuList, new Comparator<AuthMenu>() {
                public int compare(AuthMenu a1, AuthMenu a2) {
                    if (a1.getSort() != null && a2.getSort() != null) {
                        return a1.getSort() - a2.getSort();
                    } else if (a1.getSort() != null) {
                        return 1;
                    } else if (a2.getSort() != null) {
                        return -1;
                    } else {
                        return (int) (a1.getId() - a2.getId());
                    }
                }
            });
            return menuList;
        }
        return null;
    }

    /**
     * 获取符合vue-router菜单显示使用的多级结构树
     */
    private List<Map<String, Object>> menuTree(List<AuthMenu> menus) {
        List<Map<String, Object>> result = new ArrayList<>();
        Map<Long, List<AuthMenu>> midMap = new LinkedHashMap<>();
        for (AuthMenu data : menus) {
            if (!midMap.containsKey(data.getParentId())) {
                midMap.put(data.getParentId(), new ArrayList<>());
            }
            midMap.get(data.getParentId()).add(data);
        }
        result.addAll(menuPushTreeData(new ArrayList<Map<String, Object>>(), midMap, 10L));//零售信息管理系统
        result.addAll(menuPushTreeData(new ArrayList<Map<String, Object>>(), midMap, 99L));//权限管理系统
        return result;
    }

    public List<Map<String, Object>> menuPushTreeData(List<Map<String, Object>> result, Map<Long, List<AuthMenu>> midMap, Long parentId) {
        if (midMap.containsKey(parentId)) {
            for (AuthMenu firMenu : midMap.get(parentId)) {
                Map<String, Object> map = new HashMap<>();

                map.put("path", firMenu.getPath());
                map.put("component", firMenu.getUrl());
                if (!StringUtil.isEmpty(firMenu.getRedirect())) {
                    map.put("redirect", firMenu.getRedirect());
                }
                Map<String, Object> meta = new HashMap<>();
                meta.put("id", firMenu.getId());
                meta.put("name", firMenu.getName());
                meta.put("icon", firMenu.getIcon());
                map.put("meta", meta);
                if (midMap.containsKey(firMenu.getId())) {
                    List<Map<String, Object>> childs = new ArrayList<>();
                    for (AuthMenu secondMenu : midMap.get(firMenu.getId())) {
                        Map<String, Object> child = new HashMap<>();
                        child.put("path", secondMenu.getPath());
                        child.put("component", secondMenu.getUrl());
                        meta = new HashMap<>();
                        meta.put("id", secondMenu.getId());
                        meta.put("name", secondMenu.getName());
                        meta.put("icon", secondMenu.getIcon());
                        child.put("meta", meta);
                        if (midMap.containsKey(secondMenu.getId())) {
                            child.put("children", menuPushTreeData(new ArrayList<Map<String, Object>>(), midMap, secondMenu.getId()));
                        }
                        childs.add(child);
                    }
                    map.put("children", childs);
                }
                result.add(map);
            }
        }
        return result;
    }

    /**
     * 获取符合element使用的多级结构树
     */
    public List<Map<String, Object>> treeData() {
        List<Map<String, Object>> result = new ArrayList<>();
        List<AuthMenu> datas = menuRep.execHql("from AuthMenu where flag=0 order by sort");
        Map<Long, List<AuthMenu>> midMap = new HashMap<>();
        for (AuthMenu data : datas) {
            if (!midMap.containsKey(data.getParentId())) {
                midMap.put(data.getParentId(), new ArrayList<>());
            }
            midMap.get(data.getParentId()).add(data);
        }
        return pushTreeData(result, midMap, 0L);
    }

    private List<Map<String, Object>> pushTreeData(List<Map<String, Object>> result, Map<Long, List<AuthMenu>> midMap, Long parentId) {
        for (AuthMenu firMenu : midMap.get(parentId)) {
            Map<String, Object> map = new HashMap<>();
            map.put("id", firMenu.getId());
            map.put("name", firMenu.getName());
            map.put("parentId", firMenu.getParentId());
            if (midMap.containsKey(firMenu.getId())) {
                List<Map<String, Object>> childs = new ArrayList<>();
                for (AuthMenu secondMenu : midMap.get(firMenu.getId())) {
                    Map<String, Object> child = new HashMap<>();
                    child.put("id", secondMenu.getId());
                    child.put("name", secondMenu.getName());
                    child.put("parentId", secondMenu.getParentId());
                    child.put("parentName", firMenu.getName());
                    if (midMap.containsKey(secondMenu.getId())) {
                        child.put("children", pushTreeData(new ArrayList<Map<String, Object>>(), midMap, secondMenu.getId()));
                    }
                    childs.add(child);
                }
                map.put("children", childs);
            }
            result.add(map);
        }
        return result;
    }
}
